package it.univaq.mancoosi.injectors.systemconfiguration.managers.ubuntu;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.util.EcoreUtil;

import it.univaq.mancoosi.injectors.systemconfiguration.managers.XFontCacheManager;
import it.univaq.mancoosi.mancoosimm.File;
import it.univaq.mancoosi.mancoosimm.Module;
import it.univaq.mancoosi.mancoosimm.ModuleCache;
import it.univaq.mancoosi.mancoosimm.XFont;
import it.univaq.mancoosi.mancoosimm.XFontCache;

public class UbuntuXFontCacheManager extends XFontCacheManager {
	
	ArrayList<String> xfontCachesPaths = new ArrayList<String>();
	ArrayList<String> xfontPaths = new ArrayList<String>();
	protected boolean syncronizeMode = false;
	
	public UbuntuXFontCacheManager(){
		super();
	}

	public static XFontCacheManager getInstance() {
		if (INSTANCE == null)
			INSTANCE = new UbuntuXFontCacheManager();
		return INSTANCE;
	}

	@Override
	public void createXFontCachesFromSystem() {
		syncMap();
		xfontPaths.add("/usr/local/share/fonts"); 
		xfontPaths.add("/usr/share/fonts");
		
//		xfontPaths.add("/home/martina/font"); 
		
		Iterator<String> i = xfontPaths.iterator();
		
		while (i.hasNext()) {
			
			String path = i.next();
			java.io.File file = new java.io.File(path);
			
			if(file.exists()){				
				findXFontCachePath(file);
			}
		}
	}
	
	protected void findXFontCachePath(java.io.File file){
		
		ArrayList<XFontCache> caches = new ArrayList<XFontCache>();

		if(UbuntuEnvironmentManager.getInstance().getEnvironment().getXfontCaches() != null){
			caches.addAll(UbuntuEnvironmentManager.getInstance().getEnvironment().getXfontCaches());
		}
		
		Boolean exists = false;
		String currentCachePath;
		java.io.File currentCacheFile;
		if(file.isDirectory()){
			for(int i=0; i<file.listFiles().length; i++){
				if(file.listFiles()[i].isDirectory()){
					findXFontCachePath(file.listFiles()[i]);
				}else{
					if (!existsXFontCache(file.listFiles()[i].getParentFile().getParentFile().getPath())) {
						currentCachePath = file.listFiles()[i].getParentFile().getParentFile().getPath();
						currentCacheFile = file.listFiles()[i].getParentFile().getParentFile();
						if(xfontCachesPaths.size() == 0){
							xfontCachesPaths.add(currentCachePath);
							XFontCache newXFontCache = factory.createXFontCache();
							UbuntuFileSystemManager.getInstance().createFile(file.getParentFile().getPath());
							String path = file.getParentFile().getPath();
							newXFontCache.setLocation(path);
							caches.add(newXFontCache);
							this.xfontCacheMap.put(newXFontCache.getLocation(), newXFontCache);
							syncronizeMode = false;
							createXFonts(currentCacheFile, newXFontCache);
						}else{
							for(int j=0; j<xfontCachesPaths.size(); j++){
								if(xfontCachesPaths.get(j).equals(currentCachePath)){
									exists = true;
								}
							}
							if(!exists){
								currentCachePath = file.listFiles()[i].getParentFile().getParentFile().getPath();
								currentCacheFile = file.listFiles()[i].getParentFile().getParentFile();
								xfontCachesPaths.add(currentCachePath);
								
								XFontCache newXFontCache = factory.createXFontCache();
								UbuntuFileSystemManager.getInstance().createFile(file.getParentFile().getPath());
								String path = file.getParentFile().getPath();
								newXFontCache.setLocation(path);
								caches.add(newXFontCache);
								this.xfontCacheMap.put(newXFontCache.getLocation(), newXFontCache);
								syncronizeMode = false;
								createXFonts(currentCacheFile, newXFontCache);
							}
						}
					}
				}
			}
			UbuntuEnvironmentManager.getInstance().getEnvironment().getXfontCaches().addAll(caches);
		}
	}
	
	protected void createXFonts(java.io.File cacheFile, XFontCache newXFontCache){

		ArrayList<XFont> xfontsList = new ArrayList<XFont>();
		
		if(syncronizeMode){
			if(UbuntuEnvironmentManager.getInstance().getEnvironment().getXfontCaches() != null){			
				int indexXFC = UbuntuEnvironmentManager.getInstance().getEnvironment().getXfontCaches().indexOf(newXFontCache);
				XFontCache xfc = UbuntuEnvironmentManager.getInstance().getEnvironment().getXfontCaches().get(indexXFC);
				xfontsList.addAll(xfc.getXfonts());
			}
		}

			java.io.File xfontsDirectory[] = cacheFile.listFiles();

			for(int i=0; i<xfontsDirectory.length; i++){
				if(xfontsDirectory[i].isDirectory()){
					if (!existsXFont(xfontsDirectory[i].getPath())) {
						XFont xfont = factory.createXFont();
						xfont.setName(xfontsDirectory[i].getPath());			
						java.io.File fontsList[] = xfontsDirectory[i].listFiles();
						syncronizeMode = false;
						createFilesForXFont(fontsList, xfont);
						this.xfontMap.put(xfont.getName(), xfont);
						xfontsList.add(xfont);
					}
				}	
			}
			newXFontCache.getXfonts().addAll(xfontsList);
	}
	
	protected void createFilesForXFont(java.io.File fontsList[], XFont xfont){
		
		ArrayList<File> files = new ArrayList<File>();
		
		if(syncronizeMode){
			if(UbuntuEnvironmentManager.getInstance().getEnvironment().getXfontCaches() != null){	
				int indexXFC = UbuntuEnvironmentManager.getInstance().getEnvironment().getXfontCaches().indexOf(xfont.getXfontCache());
				XFontCache xfc = UbuntuEnvironmentManager.getInstance().getEnvironment().getXfontCaches().get(indexXFC);
				
				int indexXFont = xfc.getXfonts().indexOf(xfont);
				XFont xf = xfc.getXfonts().get(indexXFont);
				
				files.addAll(xf.getFile());
			}
		}
		
			for(int j=0; j<fontsList.length; j++){
			if(fontsList[j].isFile()){			
	
				UbuntuFileSystemManager.getInstance().createFile(xfont.getName());
				
				java.io.File fontFile = new java.io.File(fontsList[j].getPath());
	
				if(fontFile.exists()){
					if (!existsFile(fontsList[j].getPath())) {
						File fontModelFile = UbuntuFileSystemManager.getInstance()
						.createFile(fontFile.getPath());					
						files.add(fontModelFile);
						this.filesMap.put(fontModelFile.getLocation(), fontModelFile);
					}
				}
			}
		}
			xfont.getFile().addAll(files);
	}

	@Override
	public void synchronize() throws IOException {
		createXFontCachesFromSystem();
		Iterator<XFontCache> cacheIterator = this.xfontCacheMap.values().iterator();
		while (cacheIterator.hasNext()) {
			XFontCache curr = cacheIterator.next();
			if (isMissingXFontCacheInTheSystem(curr.getLocation())) {
				//delete cache 
				this.xfontCacheMap.remove(curr);

				EList<XFont> fonts = curr.getXfonts();
				for(int j=0; j<fonts.size(); j++){
					EList<File> files = fonts.get(j).getFile();
					for(int k=0; k<files.size(); k++){
						//delete files for this font
						this.filesMap.remove(files.get(k));
						UbuntuFileSystemManager.getInstance().deleteFile(files.get(k).getLocation());
					}
					//delete fonts for this cache
					this.xfontMap.remove(fonts.get(j));
					UbuntuFileSystemManager.getInstance().deleteFile(fonts.get(j).getName());				
				}
				EcoreUtil.delete(curr);
			}else{
				//update fonts list for this cache
				java.io.File xfontCacheFile = new java.io.File(curr.getLocation());
				syncronizeMode = true;
				createXFonts(xfontCacheFile, curr);
				
				Iterator<XFont> fontIterator = this.xfontMap.values().iterator();

				while (fontIterator.hasNext()) {
					XFont currFont = fontIterator.next();
					if((currFont.getName()).contains(curr.getLocation())){
						if (isMissingXFontInTheSystem(currFont.getName())) {
							//delete files for this xfont
							EList<File> files = currFont.getFile();
							for(int k=0; k<files.size(); k++){
								this.filesMap.remove(files.get(k));
								UbuntuFileSystemManager.getInstance().deleteFile(files.get(k).getLocation());
							}
							this.xfontMap.remove(currFont);						
							UbuntuFileSystemManager.getInstance().deleteFile(currFont.getName());
							EcoreUtil.delete(currFont);
						}else{
							//update files list for this xfont
							java.io.File xfontFile = new java.io.File(currFont.getName());
							syncronizeMode = true;
							java.io.File fontsList[] = xfontFile.listFiles();
							createFilesForXFont(fontsList, currFont);
							
							Iterator<File> fileIterator = this.filesMap.values().iterator();

							while (fileIterator.hasNext()) {
								File currFile = fileIterator.next();
								if((currFile.getLocation()).contains(currFont.getName())){
									if (isMissingFileInTheSystem(currFile.getLocation())) {						
										this.filesMap.remove(currFile);						
										UbuntuFileSystemManager.getInstance().deleteFile(currFile.getLocation());
									}
								}
							}
						}
					}
				}				
			}
		}
	}
	
	public boolean isMissingFileInTheSystem(String fileLocation){
		if(UbuntuFileSystemManager.getInstance().getFile(fileLocation) != null){
			return UbuntuFileSystemManager.getInstance().getFile(fileLocation).isIsMissing();
		}else{
			return true;
		}		
//		java.io.File file = new java.io.File(fileLocation);
//		return file.exists();
	}
	
	public boolean isMissingXFontInTheSystem (String xfontLocation) {	
		if(UbuntuFileSystemManager.getInstance().getFile(xfontLocation) != null){
			return UbuntuFileSystemManager.getInstance().getFile(xfontLocation).isIsMissing();
		}else{
			return true;
		}
//		java.io.File file = new java.io.File(xfontLocation);
//		return file.exists();
	}
	
	public boolean isMissingXFontCacheInTheSystem (String xfontCacheLocation) {
		if(UbuntuFileSystemManager.getInstance().getFile(xfontCacheLocation) != null){
			return UbuntuFileSystemManager.getInstance().getFile(xfontCacheLocation).isIsMissing();
		}else{
			return true;
		}
//		java.io.File file = new java.io.File(xfontCacheLocation);
//		return file.exists();
	}

	@Override
	public Boolean existsXFont(String xfontName) {
		return this.xfontMap.containsKey(xfontName);
	}

	@Override
	public Boolean existsXFontCache(String xfontCacheName) {
		return this.xfontCacheMap.containsKey(xfontCacheName);
	}

	@Override
	public Boolean existsFile(String fileName) {
		return this.filesMap.containsKey(fileName);
	}

}
